# HG changeset patch
# User Alex Chronopoulos <achronop@gmail.com>
# Parent  b7bb31e5a851d6f8e142c39dc077e3774719eced
Bug 1342363 - Uplift wasapi fixes in Beta. r?kinetik

diff --git a/media/libcubeb/src/cubeb_wasapi.cpp b/media/libcubeb/src/cubeb_wasapi.cpp
--- a/media/libcubeb/src/cubeb_wasapi.cpp
+++ b/media/libcubeb/src/cubeb_wasapi.cpp
@@ -807,16 +807,20 @@ wasapi_stream_render_loop(LPVOID stream)
      maybe WebRTC. */
   mmcss_handle =
     stm->context->set_mm_thread_characteristics("Audio", &mmcss_task_index);
   if (!mmcss_handle) {
     /* This is not fatal, but we might glitch under heavy load. */
     LOG("Unable to use mmcss to bump the render thread priority: %x", GetLastError());
   }
 
+  // This has already been nulled out, simply exit.
+  if (!emergency_bailout) {
+    is_playing = false;
+  }
 
   /* WaitForMultipleObjects timeout can trigger in cases where we don't want to
      treat it as a timeout, such as across a system sleep/wake cycle.  Trigger
      the timeout error handling only when the timeout_limit is reached, which is
      reset on each successful loop. */
   unsigned timeout_count = 0;
   const unsigned timeout_limit = 5;
   while (is_playing) {
@@ -1158,22 +1162,26 @@ bool stop_and_join_render_thread(cubeb_s
 
   /* Wait five seconds for the rendering thread to return. It's supposed to
    * check its event loop very often, five seconds is rather conservative. */
   DWORD r = WaitForSingleObject(stm->thread, 5000);
   if (r == WAIT_TIMEOUT) {
     /* Something weird happened, leak the thread and continue the shutdown
      * process. */
     *(stm->emergency_bailout) = true;
+    // We give the ownership to the rendering thread.
+    stm->emergency_bailout = nullptr;
     LOG("Destroy WaitForSingleObject on thread timed out,"
         " leaking the thread: %d", GetLastError());
     rv = false;
   }
   if (r == WAIT_FAILED) {
     *(stm->emergency_bailout) = true;
+    // We give the ownership to the rendering thread.
+    stm->emergency_bailout = nullptr;
     LOG("Destroy WaitForSingleObject on thread failed: %d", GetLastError());
     rv = false;
   }
 
 
   // Only attempts to close and null out the thread and event if the
   // WaitForSingleObject above succeeded, so that calling this function again
   // attemps to clean up the thread and event each time.
@@ -1798,19 +1806,16 @@ void wasapi_stream_destroy(cubeb_stream 
   XASSERT(stm);
 
   // Only free stm->emergency_bailout if we could not join the thread.
   // If we could not join the thread, stm->emergency_bailout is true 
   // and is still alive until the thread wakes up and exits cleanly.
   if (stop_and_join_render_thread(stm)) {
     delete stm->emergency_bailout.load();
     stm->emergency_bailout = nullptr;
-  } else {
-    // If we're leaking, it must be that this is true.
-    assert(*(stm->emergency_bailout));
   }
 
   unregister_notification_client(stm);
 
   SafeRelease(stm->reconfigure_event);
   SafeRelease(stm->refill_event);
   SafeRelease(stm->input_available_event);
 
@@ -1865,21 +1870,21 @@ int stream_start_one_side(cubeb_stream *
     return CUBEB_ERROR;
   }
 
   return CUBEB_OK;
 }
 
 int wasapi_stream_start(cubeb_stream * stm)
 {
+  auto_lock lock(stm->stream_reset_lock);
+
   XASSERT(stm && !stm->thread && !stm->shutdown_event);
   XASSERT(stm->output_client || stm->input_client);
 
-  auto_lock lock(stm->stream_reset_lock);
-
   stm->emergency_bailout = new std::atomic<bool>(false);
 
   if (stm->output_client) {
     int rv = stream_start_one_side(stm, OUTPUT);
     if (rv != CUBEB_OK) {
       return rv;
     }
   }
@@ -1932,16 +1937,17 @@ int wasapi_stream_stop(cubeb_stream * st
       }
     }
 
 
     stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
   }
 
   if (stop_and_join_render_thread(stm)) {
+    // This is null if we've given the pointer to the other thread
     if (stm->emergency_bailout.load()) {
       delete stm->emergency_bailout.load();
       stm->emergency_bailout = nullptr;
     }
   }
 
   return CUBEB_OK;
 }
